package org.wattdepot.simulation.basic;

import java.util.Random;
import org.wattdepot.simulation.core.Simulation;

/**
 * Defines a Data object that returns a random value.
 * 
 * @author BaoHuy Ung, Alan Lee, Edwin Lim, and Anthony Xu.
 * 
 */
public class Basic extends Simulation {

  /** Random object. */
  private Random m_Random;
  /**Temporary instance to hold data.*/
  private int temp = 0;
  /** Temporary instance to hold data(float).*/
  private float serverEnergy = 0;
  /** Holds energy data as type unsigned 16-bit. */
  private int energy = 0;
  /** Holds accumulated energy data as int-bits. */
  private int energyBits = 0;
  /** Limit value. */
  private int limit = 0;
  /** Test value. */
  private int test = 0;
  /** Holds overflow value. */
  private int overflow = 0;
  /** Holds bit value. */
  private int bits = 0;
  /** Holds PT1 bit value. */
  private int ptBits = 0;
  /** Holds PT2 bit value. */
  private int pt2Bits = 0;
  /** Holds the sum. */
  private float sum = 0;

  /**
   * Constructs a basic object.
   */
  public Basic() {
    m_Random = new Random();
  }

  /**
   * Constructs a new <tt>RandomDigitalIn</tt> with a given <tt>Random</tt> instance.
   * 
   * @param rnd Random instance.
   */
  public Basic(Random rnd) {
    m_Random = rnd;
  }

  /**
   * Checks to see if m_Random is set.
   * 
   * @return boolean if m_random is set.
   */
  @Override
  public boolean isSet() {
    return m_Random.nextBoolean();
  }

  /**
   * Returns true.
   * 
   * @return true
   */
  @Override
  public boolean isValid() {
    return true;
  }

  /**
   * Generates a random power value.
   * 
   * @return power value
   */
  @Override
  public float createRandomValue() {
    float randomval = (m_Random.nextFloat() + 10) * 1000;
    setIntBits(randomval);
    return randomval / 1000;
  }

  /**
   * Returns power in bits.
   * 
   * @return power in bits.
   */
  @Override
  public int getIntBits() {
    return bits;
  }

  /**
   * Converts to int bits.
   * 
   * @param x Input float to be converted.
   */
  @Override
  public void setIntBits(float x) {
    bits = Float.floatToIntBits(x);
  }
  
  /**
   * Accumulated energy value as float returned.
   * 
   * @return int bits of the float sum.
   */
  @Override
  public int getEnergyBits() {
    return energyBits;
  }
  
  /**
   * Convert float to int-bits and stored until called.
   * 
   * @param x the sum of accumulated energy.
   */
  @Override
  public void setEnergyBits(float x) {
    energyBits = Float.floatToIntBits(x);
  }
  
  /**
   * Returns energy value.
   * 
   * @return energy value.
   */
  @Override
  public int getEnergy() {
    return energy;
  }
  
  /**
   * Sets the latest energy data from WattDepot server.
   * @param a latest WattDepot server energy
   */
  @Override
  public void setServerEnergy(int a) {
    temp = a;
  }
  
  /**
   * Returns latest energy data from WattDepot server.
   * @return WattDepot server energy data
   */
  @Override
  public int getServerEnergy() {
    return temp;
  }
  
  
  /**
   * Sets the energy value.
   * 
   * @param a The energy value.
   */
  @Override
  public void setEnergy(int a) {
    energy = a;
  }
  
  /**
   * Returns the limit.
   * 
   * @return Limit value.
   */
  @Override
  public int getLimit() {
    return limit;
  }

  /**
   * Sets the limit value.
   * 
   * @param a The limit value.
   */
  @Override
  public void setLimit(int a) {
    limit = a;
  }

  /**
   * Computes the total energy used.
   * 
   * @param powerBitValue The randomly generated power level.
   * @return The energy value.
   */
  @Override
  public float totalAccumulatedEnergy(int powerBitValue) {
    int power = powerBitValue;
    float level = (Float.intBitsToFloat(power) / 3600) / 1000;
    sum += level;
    double serverData = (double) getServerEnergy() / 10;
    setEnergyBits(sum + (float)serverData + getEnergyFloat());
    if (sum >= 0.1) {
      float converter = sum * 10;
      test = (int) converter + getServerEnergy();
      if (test >= 65535) {
        overflow = test / 65535;
        setLimit(overflow);
        test = test % 65535;
      }
    }
    else {
      test = getServerEnergy();
      if (test == 0) {
        test = 1;
      }
      else if (test >= 65535) {
        overflow = test / 65535;
        setLimit(overflow);
        test = test % 65535;
      }
    }
    setEnergy(test);
    return sum;
  }

  /**
   * Generates a random value for the Potential Transformer #1.
   * 
   * @return Potential Transformer #1 data.
   */
  @Override
  public float createRandomPT1Value() {
    float randomval = (m_Random.nextInt(500001));
    if (randomval < 50) {
      randomval = 50;
    }
    setBitsForPT(randomval);
    return randomval;
  }

  /**
   * Returns the Potential Transformer #1 value in bits.
   * 
   * @return Potential Transformer #1 value in bits.
   */
  @Override
  public int getBitsForPT() {
    return ptBits;
  }

  /**
   * Sets the Potential Transformer #1 value in bits.
   * 
   * @param x Potential Transformer #1 value to be converted to bits.
   */
  @Override
  public void setBitsForPT(float x) {
    ptBits = Float.floatToIntBits(x);
  }

  /**
   * Generates a random value for the Potential Transformer #2.
   * 
   * @return Potential Transformer #2 data.
   */
  @Override
  public int createRandomPT2Value() {
    int randomval = (m_Random.nextInt(40001));
    if (randomval < 50) {
      randomval = 50;
    }
    setPT2(randomval);
    return randomval;
  }

  /**
   * Returns the Potential Transformer #2 value in bits.
   * 
   * @return Potential Transformer #2 value in bits.
   */
  @Override
  public int getPT2() {
    return pt2Bits;
  }

  /**
   * Sets the Potential Transformer #2 value in bits.
   * 
   * @param x Potential Transformer #2 value in bits.
   */
  @Override
  public void setPT2(int x) {
    pt2Bits = x;
  }

  /**
   * Generates a random value for the Current Transformer #1.
   * 
   * @return Current Transformer #1 data.
   */
  @Override
  public int createRandomCT1Value() {
    int randomval = (m_Random.nextInt(50001));
    if (randomval == 0) {
      randomval = 1;
    }
    return randomval;
  }

  /**
   * Generates a random value for the Current Transformer #2.
   * 
   * @return Current Transformer #2 data.
   */
  @Override
  public int createRandomCT2Value() {
    int randomval = (m_Random.nextInt(1000) + 1);
    if ((randomval % 5) == 0) {
      randomval = 5;
    }
    else {
      randomval = 1;
    }
    return randomval;
  }

  /**
   * Sets the latest energy data from WattDepot server as float.
   * 
   * @param a latest WattDepot server energy.
   */
  @Override
  public void setEnergyFloat(double a) {
    serverEnergy = (float)a; 
  }
  
  /**
   * Return latest energy data as float from WattDepot server.
   * 
   * @return WattDepot server energy data.
   */
  @Override
  public float getEnergyFloat() {
    return serverEnergy;
  }
  
}